package com.hangsu.train.components.service.impl;

import com.hangsu.train.common.utils.Digests;
import com.hangsu.train.components.constants.JwtConstant;
import com.hangsu.train.components.constants.UserConstant;
import com.hangsu.train.components.convert.UserConvert;
import com.hangsu.train.components.dao.RoleDao;
import com.hangsu.train.components.dao.UserDao;
import com.hangsu.train.components.entity.Role;
import com.hangsu.train.components.entity.User;
import com.hangsu.train.components.params.*;
import com.hangsu.train.components.service.UserService;
import com.hangsu.train.components.web.utils.UserUtils;
import com.hangsu.train.core.exception.Assert;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import jakarta.annotation.Resource;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    private UserDao userDao;
    private RoleDao roleDao;
    private UserConvert userConvert;


    @Resource
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Resource
    public void setRoleDao(RoleDao roleDao) {
        this.roleDao = roleDao;
    }

    @Resource
    public void setUserConvert(UserConvert userConvert) {
        this.userConvert = userConvert;
    }

    @Override
    public User login(LoginParam param) {
        User user = userDao.getUserByAccount(param.getUserName());
        if (user!=null){
            String passwordHex = Hex.encodeHexString(Digests.md5(param.getPassword().getBytes(), user.getSalt().getBytes()));
            if (StringUtils.equals(user.getPassword(), passwordHex)) {
                return user;
            }
        }
        return null;
    }

    @Override
    public String genToken(User user) throws JOSEException {
        MACSigner macSigner = new MACSigner(JwtConstant.SECRET);
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);

        List<Role> roles= roleDao.getRolesByUserCode(user.getUserCode());

        List<String> strings =  roles.stream().map(Role::getName).collect(Collectors.toList());
        JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                .subject(user.getPhone())
                .expirationTime(new Date(System.currentTimeMillis()))
                .claim("userName", user.getUserName())
                .claim("phone", user.getPhone())
                .claim("role",StringUtils.join(strings,","))
                .claim("photo",user.getPhoto())
                .build();

        SignedJWT signedJWT = new SignedJWT(jwsHeader, claimsSet);
        signedJWT.sign(macSigner);
        return signedJWT.serialize();
    }

    @Override
    public User detail(String subject) {
        return userDao.getUserByCode(subject);
    }

    @Override
    public void addUser(UserAddParam param) {
        User user = userConvert.convert(param);
        User user1= userDao.getUserByPhone(param.getPhone());
        Assert.isNull(user1,"当前手机号已经注册");
        user.setUserCode(UUID.randomUUID().toString().replaceAll("-",""));
        Random random = new Random();
        StringBuffer buf = new StringBuffer("0000");
        String seqStr = String.valueOf(random.nextInt(1000) + 1);
        buf.replace(buf.length() - seqStr.length(), buf.length(), seqStr);
        user.setSalt(buf.toString());
        String passwordHex = Hex.encodeHexString(Digests.md5(param.getPassword().getBytes(), buf.toString().getBytes()));
        user.setPassword(passwordHex);
        user.setState(1);
        userDao.insert(user);
    }

    @Override
    public Page<User> list(UserSearchParam param) {
        PageRequest request=PageRequest.of(param.getPage(), param.getPageSize());
        User query=new User();
        if(StringUtils.isNotEmpty(param.getUserName())){
            query.setUserName(param.getUserName());
        }
        List<User> list =  userDao.getUserList(query,request.getOffset(),request.getPageSize());
        long count = userDao.getUserCount(query);
        return new PageImpl<>(list,request,count);
    }

    @Override
    public User getUserByAccount(String account) {
        return userDao.getUserByPhone(account);
    }

    @Override
    public void freeze(String userCode,int state) {
        User u=userDao.getUserByCode(userCode);
        if (u!=null) {
            User user=new User();
            user.setId(u.getId());
            user.setState(state);
            userDao.updateSelective(user);
        }
    }

    @Override
    public void update(UserUpdateParam updateParam) {
        User user=userConvert.convert(updateParam);
        User currUser= UserUtils.getCurrUser();
        user.setId(currUser.getId());
        userDao.updateSelective(user);
    }

    @Override
    public List<User> getUserByCodes(List<String> codes) {
        return userDao.getUsers(codes);
    }
}